#pragma once

#include<memory>
#include<functional>
#include"fields.hpp"

namespace Abstract
{
    using namespace std;
    using namespace MessType;
    class BaseMessage
    {
        public:
        using ptr=std::shared_ptr<BaseMessage>;
        virtual ~BaseMessage()
        {}
        void SetId(const string&id)
        {
            _rid=id;
        }
        virtual string GetRid(){ return _rid;}
        virtual void SetMtype(Mtype mtype){   _mtype=mtype;}
        virtual Mtype GetMtype()    {return _mtype;}
        virtual string Serialize()=0;
        virtual bool Deserialize(const string &msg)=0;
        virtual bool Check()=0;
        protected:
        Mtype _mtype; 
        string _rid;
    };

    class BaseBuffer{
        public:
        using ptr =shared_ptr<BaseBuffer>;
        virtual size_t ReadAbleSize()=0;
        virtual int32_t PeekInt32()=0;
        virtual void RetrieveInt32()=0;
        virtual int32_t ReadInt32()=0;
        virtual string RetrieveAsString(size_t len)=0;
    };

    class BaseProtocol{
        public:
        using ptr=shared_ptr<BaseProtocol>;
        virtual bool CanProcessed(const BaseBuffer::ptr &buf)=0;
        virtual bool OnMessage(const BaseBuffer::ptr &buf, BaseMessage::ptr &msg)=0;
        virtual string Serialize(const BaseMessage::ptr &msg)=0;
    };

    class BaseConnection{
        public:
        using ptr=shared_ptr<BaseConnection>;
        virtual void Send(const BaseMessage ::ptr &msg)=0;
        virtual void ShutDown()=0;
        virtual bool Connected()=0;
    };
    
    using ConncectionCB=function<void(const BaseConnection::ptr&)>;
    using CloseCB=function<void(const BaseConnection::ptr&)>;
    using MessageCB=function<void(const BaseConnection::ptr&,BaseMessage::ptr&)>;


    class BaseServer{
        public:
        using ptr=shared_ptr<BaseServer>;
        virtual void SetConnectionCB(const ConncectionCB &cb)
        {
            _cb_connection =cb;
        }
        virtual void SetCloseCB(const CloseCB&cb)   {_cb_close=cb;}
        virtual void SetMessageCB(const MessageCB &cb)  {_cb_message=cb;}
        virtual void Start()=0;
        protected:
        ConncectionCB _cb_connection;
        CloseCB _cb_close;
        MessageCB _cb_message;
    };

    class BaseClient{
        public:
        using ptr=shared_ptr<BaseClient>;
         virtual void SetConnectionCB(const ConncectionCB &cb)
        {
            _cb_connection =cb;
        }
        virtual void SetCloseCB(const CloseCB&cb)   {_cb_close=cb;}
        virtual void SetMessageCB(const MessageCB &cb)  {_cb_message=cb;}
        virtual void Connect()=0;
        virtual void Shutdown()=0;
        virtual bool Send(const BaseMessage::ptr&msg)=0;
        virtual BaseConnection::ptr Conncection()=0;
        virtual bool Connected()=0;
        protected:
        ConncectionCB _cb_connection;
        CloseCB _cb_close;
        MessageCB _cb_message;
    };

} // namespace Abstruct
